---
sidebar_position: 6
title: Guide - Authentication
sidebar_label: Authentication
---

# Authentication

Authentication in Hyper Fetch consists of two steps. We will introduce changes in the
**[Client](/documentation/02-core/client.mdx)** instance and subsequent requests created from it.

---

#### First, we need to add code for request authentication

In the example below we are doing it by adding a token header to the currently sent request.

```ts
export const client = new Client({ url }).onAuth((request) => {
  // Redux store or any other storage to get current value of token
  const state = store.getState();
  const authToken = state.auth.token;

  // For every authenticated request we want to
  // add the header with token and return the extended request
  return request.setHeaders({
    ...request.headers,
    Authorization: `Bearer ${authToken}`,
  });
});
```

#### The second step is to put the `auth: true` option in the request to make it available for `onAuth` method of client.

```ts
export const getUsers = client.createRequest()({
  endpoint: "/users",
  auth: true,
});
```

That's it, from now on, each request made using this request will be authenticated with our token.

### Refresh token

To refresh the token, we can add a special `onError` interceptor to our **[Client](/documentation/02-core/client.mdx)**.
It intercepts errors received in our requests and it is asynchronous, which allows for efficient handling of such cases.

To properly **`avoid the infinite refresh loop`** of the token, we need to protect ourselves by setting the `used` field
to **true** thanks to the appropriate method `setUsed`. This will allow us to easily verify whether our commend has
already gone through the intercept process or not.

### Example

```ts
export const client = new Client({ url }).onError(async (response, request) => {
  const status = response[2];
  const refreshToken = localStorage.getItem(REFRESH_TOKEN_STORAGE_FIELD);

  // Check if request has the used value - this will ensure you to
  // not go into infinite loop and trigger this operation only once
  if (!request.used && refreshToken && status === 401) {
    // Prepare the refresh token request
    const postRefreshToken = client.createRequest<LoginResponse, LoginData>()({
      endpoint: "/refresh-token",
      method: "POST",
    });

    // Call the request to receive new tokens
    const [data] = await postRefreshToken.setData({ refreshToken }).exec();

    if (data) {
      // Safe the new tokens
      localStorage.setItem(TOKEN_STORAGE_FIELD, data.token);
      localStorage.setItem(REFRESH_TOKEN_STORAGE_FIELD, data.refreshToken);
      // Repeat the request and set it "used"
      return request.setUsed(true).send();
    }
  }
  // Return the initial response is something goes wrong
  return response;
});
```
